//
//  MKUIListView.h
//  MKUI
//  列表视图，接口依照UITableView设计。可以设置列表头部视图、尾部视图、背景视图。可以添加分组，分组可以设置分组头部视图，分组尾部视图，可以往分组添加的单元格视图。分组内部的单元格可以设置分隔线样式。与UITableView不同的是，UIListView中的所有视图，都没有进行复用，视图都是直接添加到UIScrollView中显示，因此能最大程度保持滚动流畅性。在刷新指定视图时，只是重新计算视图的尺寸，然后设定该视图与后续视图的位置属性，不会从窗口中移出移入视图。
//  Created by 苏尚进 on 2022/3/24.
//  Copyright © 2022 moon. All rights reserved.
//
/**
 关于safeAreaInsets的传递机制：
 safeAreaInsets 的传递遵循一个清晰的、自顶向下的层级规则。它从窗口开始，沿着视图层级树向下传递，并且在传递过程中可以被视图控制器或父视图影响和修改。
 1. 起点：UIWindow
 UIWindow 作为整个应用的根容器，它直接知道设备物理屏幕的 Safe Area 边界。它的 safeAreaInsets 是由系统根据硬件（刘海、圆角）和软件状态（状态栏是否显示、通话录音条是否出现等）计算得出的。
 窗口将这些插入值提供给其根视图控制器（rootViewController）的视图。
 
 2. 关键角色：UIViewController
 视图控制器在 Safe Area 的传递中扮演着核心角色，因为它管理着附加的 Safe Area。
 additionalSafeAreaInsets：这是 UIViewController 的一个属性。它允许你手动增加或减少传递给其视图的 Safe Area 插入值。
 视图控制器的根视图（view） 的最终 safeAreaInsets 计算公式为：
 view.safeAreaInsets = 系统计算的safeAreaInsets + viewController.additionalSafeAreaInsets
 
 3. 向下传递：父视图到子视图
 当一个子视图被添加到父视图上时，它的 safeAreaInsets 是如何确定的呢？
 这里有一个关键规则：
 子视图的 safeAreaInsets 默认继承自其父视图的 Safe Area 边界，并相对于子视图自身在父视图中的位置进行计算。
 传递过程：

 系统先确定父视图的 Safe Area 矩形（我们称之为 parentSafeAreaFrame）。
 然后，系统会计算这个 parentSafeAreaFrame 与子视图的 frame 的交集（Intersection）。
 这个交集部分，就是子视图实际占据的 Safe Area 区域。
 最后，系统计算出子视图的四个边界与这个交集区域的四个边界之间的距离，从而得出子视图自己的 safeAreaInsets。
 4. 可以中断传递：ignoresSafeAreaInsets 属性。如果一个视图不希望受到父视图 Safe Area 的影响，它可以设置 insetsLayoutMarginsFromSafeArea = false（或对于 UIStackView 是 isLayoutMarginsRelativeArrangement = false）。
 
 特殊点：
 UIScrollView中子视图的safeAreaInsets值，与滚动方向相同的分量，都设置为了0。
 */

#import <UIKit/UIKit.h>
#import "CGGeometry+MKUI.h"

typedef NS_ENUM(NSInteger, MKUIListViewScrollDirection) {
    MKUIListViewScrollDirectionVertical,
    MKUIListViewScrollDirectionHorizontal
};

typedef enum{
    MKUIListViewSectionViewKindOfHead=0,    //头部
    MKUIListViewSectionViewKindOfFoot=1     //尾部
} MKUIListViewSectionViewKind;

typedef enum : NSUInteger {
    MKUIListViewItemAnimationFade,
    MKUIListViewItemAnimationRight,
    MKUIListViewItemAnimationLeft,
    MKUIListViewItemAnimationTop,
    MKUIListViewItemAnimationBottom,
    MKUIListViewItemAnimationNone,
    MKUIListViewItemAnimationAutomatic=100,//从中间点缩变，scale设置为0.01
} MKUIListViewItemAnimation;

typedef enum : NSUInteger {
    MKUIListViewScrollPositionNone,
    MKUIListViewScrollPositionHead,
    MKUIListViewScrollPositionMiddle,
    MKUIListViewScrollPositionFoot,
} MKUIListViewScrollPosition;

typedef enum : NSUInteger {
    MKUIListViewCellSeparatorStyleNone,
    MKUIListViewCellSeparatorStyleSingleLine,
} MKUIListViewCellSeparatorStyle;

NS_ASSUME_NONNULL_BEGIN
@class MKUIListView;
//单元格视图可以实现的协议，能够处理单元格视图被添加、被删除、被展示、被移出显示区域的事件，以及返回自身的显示尺寸
@protocol MKUIListCellViewProtocol <NSObject>
@optional
- (void)listView:(MKUIListView *)listView didAddAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(MKUIListView *)listView didDeleteAtIndexPath:(NSIndexPath *)indexPath;

- (void)listView:(MKUIListView *)listView willDisplayAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(MKUIListView *)listView didEndDisplayingAtIndexPath:(NSIndexPath *)indexPath;
- (CGSize)listView:(MKUIListView *)listView sizeThatFits:(CGSize)size atIndexPath:(NSIndexPath *)indexPath;

- (CGFloat)listView:(MKUIListView *)listView zIndexFor:(CGFloat)zIndex atIndexPath:(NSIndexPath *)indexPath;//用于临时调整view的容器的zPosition属性

- (void)listView:(MKUIListView *)listView willSelectAtIndexPath:(NSIndexPath *)indexPath;//选中指定cell的手势刚开始识别
- (void)listView:(MKUIListView *)listView didSelectAtIndexPath:(NSIndexPath *)indexPath;//选中指定cell的手势完成，成功选中cell
- (void)listView:(MKUIListView *)listView cancelSelectAtIndexPath:(NSIndexPath *)indexPath;//选中指定cell的手势被取消了
@end

//分组头、尾部视图可以实现的协议，能够处理分组头、尾部视图被添加、被删除、被展示、被移出显示区域的事件，以及返回自身的显示尺寸
@protocol MKUIListSectionViewProtocol <NSObject>
@optional
- (void)listView:(MKUIListView *)listView didAddAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (void)listView:(MKUIListView *)listView didDeleteAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;

- (void)listView:(MKUIListView *)listView willDisplayAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (void)listView:(MKUIListView *)listView didEndDisplayingAtSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (CGSize)listView:(MKUIListView *)listView sizeThatFits:(CGSize)size atSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (CGFloat)listView:(MKUIListView *)listView zIndexFor:(CGFloat)zIndex atSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;//用于临时调整view的容器的zPosition属性
@end

@protocol MKUIListViewDelegate <NSObject,UIScrollViewDelegate>
@optional
- (void)listView:(MKUIListView *)listView didAddCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(MKUIListView *)listView didDeleteCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(MKUIListView *)listView willDisplayCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)listView:(MKUIListView *)listView didEndDisplayingCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;
- (CGSize)listView:(MKUIListView *)listView sizeThatFits:(CGSize)size forCell:(UIView *)cell forIndexPath:(NSIndexPath *)indexPath;
- (CGFloat)listView:(MKUIListView *)listView zIndexFor:(CGFloat)zIndex forCell:(UIView *)cell forIndexPath:(NSIndexPath *)indexPath;//用于临时调整view的容器的zPosition属性

- (void)listView:(MKUIListView *)listView didAddSectionView:(UIView *)sectionView forSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (void)listView:(MKUIListView *)listView didDeleteSectionView:(UIView *)sectionView forSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (void)listView:(MKUIListView *)listView willDisplaySectionView:(UIView *)sectionView forSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (void)listView:(MKUIListView *)listView didEndDisplayingSectionView:(UIView *)sectionView forSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (CGSize)listView:(MKUIListView *)listView sizeThatFits:(CGSize)size forSectionView:(UIView *)sectionView forSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (CGFloat)listView:(MKUIListView *)listView zIndexFor:(CGFloat)zIndex forSectionView:(UIView *)sectionView forSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;//用于临时调整view的容器的zPosition属性

- (void)listView:(MKUIListView *)listView willSelectCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;//选中指定cell的手势刚开始识别
- (void)listView:(MKUIListView *)listView didSelectCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;//选中指定cell的手势完成，成功选中cell
- (void)listView:(MKUIListView *)listView cancelSelectCell:(UIView *)cell forItemAtIndexPath:(NSIndexPath *)indexPath;//选中指定cell的手势被取消了

#pragma mark - 定制各分组的属性
- (nullable Class)listView:(MKUIListView *)listView groupBackgroundViewClassForSetion:(NSInteger)section;//返回指定分组的groupBackgroundViewClass
- (nullable UIColor *)listView:(MKUIListView *)listView groupBackgroundColorForSection:(NSInteger)section;//返回指定分组的groupBackgroundColor
- (UIEdgeInsets)listView:(MKUIListView *)listView groupInsetsForSection:(NSInteger)section;//在group模式下，返回指定分组的groupInsets
- (CGFloat)listView:(MKUIListView *)listView groupCornerRadiusForSection:(NSInteger)section;//在group模式下，返回指定分组的groupCornerRadius
- (UIEdgeInsets)listView:(MKUIListView *)listView groupInnerInsetsForSection:(NSInteger)section;//在group模式下，返回指定分组的groupInnerInsets
- (CGFloat)listView:(MKUIListView *)listView cellInteritemSpacingForSection:(NSInteger)section;//返回指定分组的cellInteritemSpacing

#pragma mark - 定制各分组的分隔线属性
- (MKUIListViewCellSeparatorStyle)listView:(MKUIListView *)listView separatorStyleForSection:(NSInteger)section;//返回指定分组的分隔线separatorStyle
- (nullable UIColor *)listView:(MKUIListView *)listView separatorColorForSection:(NSInteger)section;//返回指定分组的分隔线separatorColor
- (nullable UIColor *)listView:(MKUIListView *)listView separatorBackgroundColorForSection:(NSInteger)section;//返回指定分组的分隔线separatorBackgroundColor
- (CGFloat)listView:(MKUIListView *)listView separatorSizeForSection:(NSInteger)section;//返回指定分组的分隔线separatorSize
- (UIEdgeInsets)listView:(MKUIListView *)listView separatorInsetsForSection:(NSInteger)section;//返回指定分组的分隔线separatorInsets
- (nullable Class)listView:(MKUIListView *)listView separatorViewClassForSection:(NSInteger)section;//返回指定分组的分隔线separatorViewClass
@end


///列表中头部视图、尾部视图、分组头部视图、分组尾部视图、分组中单元格 的显示容器
@interface MKUIListViewAttributeContainerView : UIView
@property(nonatomic,readonly) UIView *contentView;//容器
@property(nonatomic,readonly) __kindof UIView *attributeView;//被展示的视图
@property(nonatomic,readonly) MKUIListViewScrollDirection scrollDirection;
@property(nonatomic,readonly) MKCGAxis scrollAxis;
@end

/// 列表分组的模型数据
@class MKUIListView;
@interface MKUIListViewSectionModel : NSObject
@property(nonatomic,readonly) NSInteger sectionIndex;//分组索引值，NSNotFound代表不在列表中
@property(nonatomic,readonly,nullable) MKUIListView *listView;//弱引用列表视图
@property(nonatomic,readonly) NSUInteger numberOfItems;
- (void)didMoveToListView;//分组被添加或移除listview时回调,通过判断listView有没有值，可以判断是添加还是移除

- (nullable NSArray<__kindof UIView *> *)cellsForItems;
- (nullable __kindof UIView *)cellForItemAtIndex:(NSInteger)index;

- (nullable __kindof UIView *)sectionViewForKind:(MKUIListViewSectionViewKind)kind;

- (void)setSectionView:(nullable UIView *)sectionView kind:(MKUIListViewSectionViewKind)kind;
- (void)setSectionView:(nullable UIView *)sectionView kind:(MKUIListViewSectionViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation;//设置指定分组的头部/尾部视图，当sectionIndex为末尾且不存在分组时，将自动创建

- (void)deleteSection;
- (void)deleteSectionWithAnimation:(MKUIListViewItemAnimation)animation;//删除指定分组的所有视图（头、尾部和所有item）
- (void)deleteSectionView:(UIView *)sectionView;
- (void)deleteSectionView:(UIView *)sectionView withAnimation:(MKUIListViewItemAnimation)animation;//查找sectionView所在分组，然后清空sectionView对应的头部或尾部视图
- (void)reloadSection;
- (void)reloadSectionWithAnimation:(MKUIListViewItemAnimation)animation;//刷新整个分组视图，包含头部、尾部、所有item
- (void)reloadSectionView:(nullable UIView *)sectionView kind:(MKUIListViewSectionViewKind)kind;
- (void)reloadSectionView:(nullable UIView *)sectionView kind:(MKUIListViewSectionViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation;//刷新分组头部或尾部视图。nil时代表删除
- (void)reloadSectionView:(UIView *)sectionView;
- (void)reloadSectionView:(UIView *)sectionView withAnimation:(MKUIListViewItemAnimation)animation;

- (void)insertItem:(UIView *)cell atIndex:(NSInteger)index;
- (void)insertItem:(UIView *)cell atIndex:(NSInteger)index withAnimation:(MKUIListViewItemAnimation)animation;
- (void)addItem:(UIView *)cell;
- (void)addItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation;//在最后一个分组的尾部，添加item。没有分组时，会自动创建一个
- (void)deleteItemAtIndex:(NSInteger)index;
- (void)deleteItemAtIndex:(NSInteger)index withAnimation:(MKUIListViewItemAnimation)animation;
- (void)deleteItem:(UIView *)cell;
- (void)deleteItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation;
- (void)reloadItemAtIndex:(NSInteger)index;
- (void)reloadItemAtIndex:(NSInteger)index withAnimation:(MKUIListViewItemAnimation)animation;
- (void)reloadItem:(UIView *)cell;
- (void)reloadItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation;//刷新item视图，要求item要在列表中
- (void)reloadItem:(nullable UIView *)cell atIndex:(NSInteger)index;
- (void)reloadItem:(nullable UIView *)cell atIndex:(NSInteger)index withAnimation:(MKUIListViewItemAnimation)animation;//刷新item，如果cell为新的，则会删除旧的视图，替换为新视图。nil时代表删除
- (void)moveItemFromIndex:(NSInteger)fromIndex to:(NSInteger)toIndex;
- (void)moveItemFromIndex:(NSInteger)fromIndex to:(NSInteger)toIndex withAnimation:(MKUIListViewItemAnimation)animation;//将指定单元格从a位置移动到b位置

- (void)deleteView:(UIView *)view;
- (void)deleteView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation;//删除指定视图。视图可以为分组头部，尾部，分组item视图
- (void)deleteViews:(NSArray<UIView *> *)views;
- (void)deleteViews:(NSArray<UIView *> *)views withAnimation:(MKUIListViewItemAnimation)animation;//删除指定视图。视图可以为分组头部，尾部，分组item视图
- (void)reloadView:(UIView *)view;
- (void)reloadView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation;//刷新指定视图，要求视图要在列表中。视图可以为列表头、尾部，分组头部，尾部，分组item视图
- (void)reloadData;//刷新所有视图。会先移出所有视图，然后再重新添加一遍，确认操作的完整性。
- (void)reloadDataWithAnimation:(MKUIListViewItemAnimation)animation;

@property(nonatomic,assign,nullable) Class groupBackgroundViewClass;

#pragma mark - 定制各分组的属性
@property(nonatomic,strong,nullable) UIColor *groupBackgroundColor;
@property(nonatomic,assign) UIEdgeInsets groupInsets;
@property(nonatomic,assign) CGFloat groupCornerRadius;
@property(nonatomic,assign) UIEdgeInsets groupInnerInsets;
@property(nonatomic,assign) CGFloat cellInteritemSpacing;

#pragma mark - 定制各分组的分隔线属性
@property(nonatomic,assign) MKUIListViewCellSeparatorStyle separatorStyle;//分组的分隔线separatorStyle
@property(nonatomic,strong,nullable) UIColor *separatorColor;//分组的分隔线separatorColor
@property(nonatomic,strong,nullable) UIColor *separatorBackgroundColor;//分组的分隔线separatorBackgroundColor
@property(nonatomic,assign) CGFloat separatorSize;//分组的分隔线separatorSize
@property(nonatomic,assign) UIEdgeInsets separatorInsets;//分组的分隔线separatorInsets
@property(nonatomic,assign,nullable) Class separatorViewClass;//分组的分隔线separatorViewClass
@end

typedef NS_ENUM(NSInteger, MKUIListViewStyle) {
    MKUIListViewStylePlain,          // regular table view
    MKUIListViewStyleInsetGrouped,        // sections are grouped together
};

@interface MKUIListView : UIScrollView

- (instancetype)initWithFrame:(CGRect)frame style:(MKUIListViewStyle)style;
@property(nonatomic,assign) MKUIListViewStyle style;//默认为MKUIListViewStylePlain

@property(nonatomic) MKUIListViewScrollDirection scrollDirection;//滚动方向，默认为垂直滚动：MKUIListViewScrollDirectionVertical
@property(nonatomic,readonly) MKCGAxis scrollAxis;

/// 当self.frame要变化时，通过调用此方法，来保持当前显示的内容视图，在frame改变之后，还保持在中间
/// 如在ViewController的- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator中，直接调用该方法，可以在屏幕旋转之后，中心点的视图保持不变
- (void)willTransitionToSizeChange;

@property(nonatomic,readonly) NSInteger numberOfSections;
@property(nonatomic,readonly) NSInteger numberOfItems;
- (NSUInteger)numberOfItemsInSection:(NSInteger)sectionIndex;

- (CGRect)rectForSection:(NSInteger)section;//包含头尾、尾部以及所有的单元格
- (CGRect)rectForKind:(MKUIListViewSectionViewKind)kind inSection:(NSInteger)section;
- (CGRect)rectForItemAtIndexPath:(NSIndexPath *)indexPath;
- (CGRect)rectForListHeaderView;
- (CGRect)rectForListFooterView;

- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point;
- (nullable UIView *)viewAtPoint:(CGPoint)point;
- (nullable UIView *)viewThatNearestToPoint:(CGPoint)point;
- (nullable NSIndexPath *)indexPathForCell:(UIView *)cell;
- (nullable NSArray<NSIndexPath *> *)indexPathsForItemsInRect:(CGRect)rect;
- (nullable NSArray<UIView *> *)viewsInRect:(CGRect)rect;//返回指定区域内的视图，视图类型为列表头、列表尾、分组头、分组尾、单元格
- (nullable __kindof UIView *)cellForItemAtIndexPath:(NSIndexPath *)indexPath;

- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForView:(UIView *)view;
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForListHeadView;
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForListFootView;
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForSectionAtIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind;
- (nullable __kindof MKUIListViewAttributeContainerView *)containerViewForItemAtIndexPath:(NSIndexPath *)indexPath;

- (nullable NSArray<__kindof UIView *> *)cellsForItemsInSectionIndex:(NSInteger)sectionIndex;
- (nullable NSArray<__kindof UIView *> *)viewsBeforeItemAtIndexPath:(NSIndexPath *)indexPath;//返回item之前的所有视图，包含分组头、尾部，item，listHeadView
- (nullable NSArray<__kindof UIView *> *)viewsAfterItemAtIndexPath:(NSIndexPath *)indexPath;//返回item之后的所有视图，包含分组头、尾部，item，listFootView

@property(nonatomic,readonly) NSArray<__kindof UIView *> *visibleCells;
@property(nonatomic,readonly,nullable) NSArray<NSIndexPath *> *indexPathsForVisibleItems;

- (nullable MKUIListViewSectionModel *)sectionModelAtIndex:(NSInteger)sectionIndex;

- (nullable __kindof UIView *)sectionViewForSection:(NSInteger)section kind:(MKUIListViewSectionViewKind)kind;
- (NSInteger)indexForSectionView:(UIView *)sectionView kind:(nullable MKUIListViewSectionViewKind *)kind;

- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(MKUIListViewScrollPosition)scrollPosition animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion;
- (void)scrollToView:(UIView *)view atScrollPosition:(MKUIListViewScrollPosition)scrollPosition animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion;

- (void)performBatchUpdates:(void (NS_NOESCAPE ^ _Nullable)(void))updates animated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion;

- (nullable MKUIListViewSectionModel *)insertSectionAtIndex:(NSInteger)sectionIndex;//向指定位置插入一个空白的分组
- (void)insertSectionModel:(nullable MKUIListViewSectionModel *)sectionModel atIndex:(NSInteger)sectionIndex;//向指定位置插入一个空白的分组

- (nullable MKUIListViewSectionModel *)addSection;//在末尾插件一个空白分组
- (void)addSectionModel:(nullable MKUIListViewSectionModel *)sectionModel;//在末尾插件一个空白分组

- (nullable MKUIListViewSectionModel *)addSectionWithHeadView:(nullable UIView *)sectionHeadView footView:(nullable UIView *)sectionFootView;
- (nullable MKUIListViewSectionModel *)addSectionWithHeadView:(nullable UIView *)sectionHeadView footView:(nullable UIView *)sectionFootView withAnimation:(MKUIListViewItemAnimation)animation;//在末尾插件一个新的分组，指定头、尾视图
- (void)setSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind;
- (void)setSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation;//设置指定分组的头部/尾部视图，当sectionIndex为末尾且不存在分组时，将自动创建

- (void)deleteSectionViewsAtIndex:(NSInteger)sectionIndex;//删除指定分组的所有视图（头、尾部和所有item）,保留住分组的位置
- (void)deleteSectionViewsAtIndex:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation;//删除指定分组的所有视图（头、尾部和所有item）,保留住分组的位置

- (void)deleteSectionAtIndex:(NSInteger)sectionIndex;
- (void)deleteSectionAtIndex:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation;//删除指定分组的所有视图（头、尾部和所有item）
- (void)deleteSectionView:(UIView *)sectionView;
- (void)deleteSectionView:(UIView *)sectionView withAnimation:(MKUIListViewItemAnimation)animation;//查找sectionView所在分组，然后清空sectionView对应的头部或尾部视图
- (void)deleteAllSections;
- (void)deleteAllSectionsWithAnimation:(MKUIListViewItemAnimation)animation;//删除所有的分组
- (void)reloadSection:(NSInteger)sectionIndex;
- (void)reloadSection:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation;//刷新整个分组视图，包含头部、尾部、所有item
- (void)reloadSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind;
- (void)reloadSectionView:(nullable UIView *)sectionView atIndex:(NSInteger)sectionIndex kind:(MKUIListViewSectionViewKind)kind withAnimation:(MKUIListViewItemAnimation)animation;//刷新分组头部或尾部视图。nil时代表删除
- (void)reloadSectionView:(UIView *)sectionView;
- (void)reloadSectionView:(UIView *)sectionView withAnimation:(MKUIListViewItemAnimation)animation;

- (void)insertItem:(UIView *)cell atIndexPath:(NSIndexPath *)indexPath;
- (void)insertItem:(UIView *)cell atIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation;
- (void)addItem:(UIView *)cell atSectionIndex:(NSInteger)sectionIndex;
- (void)addItem:(UIView *)cell atSectionIndex:(NSInteger)sectionIndex withAnimation:(MKUIListViewItemAnimation)animation;
- (void)addItem:(UIView *)cell;
- (void)addItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation;//在最后一个分组的尾部，添加item。没有分组时，会自动创建一个
- (void)deleteItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)deleteItemAtIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation;
- (void)deleteItem:(UIView *)cell;
- (void)deleteItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation;
- (void)reloadItemAtIndexPath:(NSIndexPath *)indexPath;
- (void)reloadItemAtIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation;
- (void)reloadItem:(UIView *)cell;
- (void)reloadItem:(UIView *)cell withAnimation:(MKUIListViewItemAnimation)animation;//刷新item视图，要求item要在列表中
- (void)reloadItem:(nullable UIView *)cell atIndexPath:(NSIndexPath *)indexPath;
- (void)reloadItem:(nullable UIView *)cell atIndexPath:(NSIndexPath *)indexPath withAnimation:(MKUIListViewItemAnimation)animation;//刷新item，如果cell为新的，则会删除旧的视图，替换为新视图。nil时代表删除
- (void)moveItemFromIndexPath:(NSIndexPath *)fromIndexPath to:(NSIndexPath *)toIndexPath;
- (void)moveItemFromIndexPath:(NSIndexPath *)fromIndexPath to:(NSIndexPath *)toIndexPath withAnimation:(MKUIListViewItemAnimation)animation;//将指定单元格从a位置移动到b位置

- (void)deleteView:(UIView *)view;
- (void)deleteView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation;//删除指定视图。视图可以为列表头、尾部，分组头部，尾部，分组item视图
- (void)deleteViews:(NSArray<UIView *> *)views;
- (void)deleteViews:(NSArray<UIView *> *)views withAnimation:(MKUIListViewItemAnimation)animation;//删除指定视图。视图可以为列表头、尾部，分组头部，尾部，分组item视图
- (void)reloadView:(UIView *)view;
- (void)reloadView:(UIView *)view withAnimation:(MKUIListViewItemAnimation)animation;//刷新指定视图，要求视图要在列表中。视图可以为列表头、尾部，分组头部，尾部，分组item视图
- (void)reloadData;//刷新所有视图。会先移出所有视图，然后再重新添加一遍，确认操作的完整性。
- (void)reloadDataWithAnimation:(MKUIListViewItemAnimation)animation;
- (void)reloadDataWithAnimated:(BOOL)animated completion:(void (^ _Nullable)(BOOL finished))completion;

@property(nonatomic,strong,nullable) UIView *listHeaderView;
@property(nonatomic,strong,nullable) UIView *listFooterView;
- (void)reloadListHeaderView:(nullable UIView *)view;
- (void)reloadListHeaderView:(nullable UIView *)view withAnimation:(MKUIListViewItemAnimation)animation;//刷新列表头部视图，nil时代表删除
- (void)reloadListFooterView:(nullable UIView *)view;
- (void)reloadListFooterView:(nullable UIView *)view withAnimation:(MKUIListViewItemAnimation)animation;//刷新列表尾部视图，nil时代表删除

@property(nonatomic,strong,nullable) UIColor *groupBackgroundColor;//分组容器的背景颜色
@property(nonatomic,assign,nullable) Class groupBackgroundViewClass;//分组容器的背景视图
- (nullable Class)groupBackgroundViewClassForSetion:(NSInteger)section;
- (void)setGroupBackgroundViewClass:(Class _Nullable)groupBackgroundViewClass forSection:(NSInteger)section;

//Group模式下，cell、section的safeAreaInsets=0，容器尺寸=listView.bounds-(MAX(0,listView.safeAreaInsets-contentInsets)+groupInsets+groupInnerInsets)
//Plain模式下，plainStyleUseGroupInsets=NO，cell、section的safeAreaInsets=super.safeAreaInsets，容器尺寸=listView.bounds
//Plain模式下，plainStyleUseGroupInsets=YES，cell、section的safeAreaInsets=super.safeAreaInsets,容器尺寸=listView.bounds-(listView.contentInsets+groupInsets+groupInnerInsets)
//列表头、尾的safeAreaInsets=super.safeAreaInsets，容器尺寸=listView.bounds
@property(nonatomic,assign) UIEdgeInsets groupInsets;//MKUIListViewStyleGrouped样式时的分组容器的内边距，默认为(10,10,10,10)。cell、分隔线的尺寸会在listView的尺寸上，扣除该值
@property(nonatomic,assign) UIEdgeInsets groupInnerInsets;//MKUIListViewStyleGrouped样式时，在groupInsets框起来的区域内部，再扣除掉该值，才开始布局分组的所有cell。默认为(0,0,0,0)。cell、分隔线的尺寸会在listView的尺寸上，扣除该值s
@property(nonatomic,assign) CGFloat groupCornerRadius;//MKUIListViewStyleGrouped样式时的分组容器的圆角值，默认为10
@property(nonatomic,assign) BOOL plainStyleUseGroupInsets;//MKUIListViewStylePlain模式时，是否应用groupInsets、groupInnerInsets。默认为NO

//单元格之间的分隔线，可以通过设置透明的分隔线以及尺寸值，达到让单元格之间有指定间距的效果。
//分隔线是作为Cell的子视图来实现的。分隔线默认视图为MKUIListViewSeparatorView
@property(nonatomic,assign) MKUIListViewCellSeparatorStyle separatorStyle;//默认为MKUIListViewCellSeparatorStyleNone，没有分隔线
@property(nonatomic,strong,nullable) UIColor *separatorColor;//分隔线的颜色
@property(nonatomic,strong,nullable) UIColor *separatorBackgroundColor;//分隔线视图的背景颜色
@property(nonatomic,assign) CGFloat separatorSize;//垂直滚动时为分隔线高度，水平滚动为分隔线宽度
@property(nonatomic,assign) UIEdgeInsets separatorInsets;//分隔线的外间距，默认为zero。分隔线所占区域空间为separatorSize+separatorInsets
@property(nonatomic,assign,nullable) Class separatorViewClass;//设置为MKUIListViewCellSeparatorStyleSingleLine时，才会启动自定义的分隔线视图

@property(nonatomic,assign) CGFloat cellInteritemSpacing;//同一个分组内，cell之间的间距(如果有分隔线，那cell和下面的分隔线作为一个整体)，默认为0
@property(nonatomic,assign) CGFloat sectionInteritemSpacing;//分组之间的间距，默认为0
@property(nonatomic,strong,nullable) UIView *backgroundView;//背景视图，当滚动时，也会一直在显示区域内。
@property(nonatomic,readonly) UIView *contentView;//head、foot、section、cell的容器视图
/// 计算最合适的尺寸。
/// - Parameters:
///   - size: 容器尺寸
///   - unlimit: 是否同时不限制宽度和高度。当不限时，会计算出最适配的宽度和高度。当限制时，会有一边固定为size值
- (CGSize)sizeThatFits:(CGSize)size unlimit:(BOOL)unlimit;

#pragma mark - 定制各分组的属性
//定制的属性，优先级为：delegate的对应方法>为指定分组设置的属性>默认的全局属性，如[delegate listView:groupBackgroundColorForSection:]>[self setGroupBackgroundColor:forSection:]后的值>self.groupBackgroundColor
- (nullable UIColor *)groupBackgroundColorForSection:(NSInteger)section;//返回通过setGroupBackgroundColor:forSection:方法，指定分组的groupBackgroundColor
- (void)setGroupBackgroundColor:(nullable UIColor *)color forSection:(NSInteger)section;

- (UIEdgeInsets)groupInsetsForSection:(NSInteger)section;//在group模式下，返回指定分组的groupInsets
- (void)setGroupInsets:(UIEdgeInsets)insets forSection:(NSInteger)section;

- (CGFloat)groupCornerRadiusForSection:(NSInteger)section;//在group模式下，返回指定分组的groupCornerRadius
- (void)setGroupCornerRadius:(CGFloat)radius forSection:(NSInteger)section;

- (UIEdgeInsets)groupInnerInsetsForSection:(NSInteger)section;
- (void)setGroupInnerInsets:(UIEdgeInsets)groupInnerInsets forSection:(NSInteger)section;

- (CGFloat)cellInteritemSpacingForSection:(NSInteger)section;//返回指定分组的cellInteritemSpacing
- (void)setCellInteritemSpacing:(CGFloat)spacing forSection:(NSInteger)section;

#pragma mark - 定制各分组的分隔线属性
- (MKUIListViewCellSeparatorStyle)separatorStyleForSection:(NSInteger)section;//返回指定分组的分隔线separatorStyle
- (void)setSeparatorStyle:(MKUIListViewCellSeparatorStyle)style forSection:(NSInteger)section;

- (nullable UIColor *)separatorColorForSection:(NSInteger)section;//返回指定分组的分隔线separatorColor
- (void)setSeparatorColor:(nullable UIColor *)color forSection:(NSInteger)section;

- (nullable UIColor *)separatorBackgroundColorForSection:(NSInteger)section;//返回指定分组的分隔线separatorBackgroundColor
- (void)setSeparatorBackgroundColor:(nullable UIColor *)color forSection:(NSInteger)section;

- (CGFloat)separatorSizeForSection:(NSInteger)section;//返回指定分组的分隔线separatorSize
- (void)setSeparatorSize:(CGFloat)size forSection:(NSInteger)section;

- (UIEdgeInsets)separatorInsetsForSection:(NSInteger)section;//返回指定分组的分隔线separatorInsets
- (void)setSeparatorInsets:(UIEdgeInsets)insets forSection:(NSInteger)section;

- (nullable Class)separatorViewClassForSection:(NSInteger)section;//返回指定分组的分隔线separatorViewClass
- (void)setSeparatorViewClass:(Class)aClass forSection:(NSInteger)section;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
//列表头部、尾部、分组头部、分组尾部、单元格视图的推荐基类
@interface MKUIListViewSubViewBase : UIView<MKUIListCellViewProtocol>
@property(nonatomic,readonly) UIView *contentView;//内容容器视图,frame值会扣除掉safeAreaInsets值
- (void)layoutContentView;//设置contentView的尺寸信息
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
//视图会吸附在listView顶部
@interface MKUIListPinHeadViewBase : MKUIListViewSubViewBase<MKUIListCellViewProtocol,MKUIListSectionViewProtocol>
@property(nonatomic,readonly) CGFloat topMargginOfPinning;//吸附在顶部时，与顶部的间隔，默认为0
@property(nonatomic,assign) BOOL enablePinning;//是否允许吸附在listView顶部，默认为YES
- (void)listViewDidChangeContentOffset:(MKUIListView *)listView;//listView滚动回调。默认实现为修改containerView的tranform，使之刚好吸附在listView的顶部。子类可以重载，以实现更多效果。
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
//含有选中效果的单元格视图基类
@interface MKUIListSelectionCellViewBase : MKUIListViewSubViewBase<MKUIListCellViewProtocol>
@property(nonatomic,assign) BOOL enableSelection;//是否开启选中效果，默认为YES
@property(nonatomic,strong,nullable) UIColor *selectedBackgroundColor;//选中时的背景颜色,默认为UIColor.mk_listViewCellSelectedColor
@property(nonatomic,strong,nullable) UIView *selectedBackgroundView;//选中时的背景图
@property(nonatomic,getter=isSelected) BOOL selected;//是否选中
@property(nonatomic,copy,nullable) void(^whenSelected)(__kindof MKUIListSelectionCellViewBase *cell,BOOL selected);//select变更回调
@property(nonatomic,copy,nullable) void(^whenClick)(__kindof MKUIListSelectionCellViewBase *el);//点击回调,会自动取消选中状态。如果要自己控制选中状态，请使用whenSelected
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion;
- (void)didSelected:(BOOL)selected;
- (void)didClick;
@property(nonatomic,strong,nullable) UIColor *highlightedBackgroundColor;//高亮时的背景颜色
@property(nonatomic,getter=isHighlighted) BOOL highlighted;//是否高亮
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated;
@end
@interface MKUIListView(CellSelection)
@property(nonatomic,readonly,nullable) NSIndexPath *indexPathForSelectedItem;
@property(nonatomic,readonly,nullable) NSArray<NSIndexPath *> *indexPathsForSelectedItems;
- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(MKUIListViewScrollPosition)scrollPosition;
- (void)selectItem:(nullable MKUIListSelectionCellViewBase *)cell animated:(BOOL)animated scrollPosition:(MKUIListViewScrollPosition)scrollPosition;
- (void)deselectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated;
- (void)deselectItem:(nullable MKUIListSelectionCellViewBase *)cell animated:(BOOL)animated;
- (void)deselectAllItemsWithAnimated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
@interface UIView(MKUIListView)
@property(nonatomic,readonly,nullable) MKUIListView *mk_listView;
@property(nonatomic,readonly,nullable) __kindof MKUIListViewAttributeContainerView *mk_attributeContainerInListView;//返回最近的listCell容器
- (void)mk_reloadInListViewWithAnimation:(MKUIListViewItemAnimation)animation;
- (void)mk_reloadInListView;

@property(nonatomic,readonly,nullable) __kindof UIView *mk_nearestAttributeViewInListView;//返回最近的list容器中的视图
@end
NS_ASSUME_NONNULL_END

NS_ASSUME_NONNULL_BEGIN
//默认的单元分隔线视图
@interface MKUIListViewSeparatorView : UIView
@property(nonatomic,strong) UIView *lineView;
@property(nonatomic,strong,nullable) UIColor *separatorColor;
@property(nonatomic,assign) CGFloat separatorSize;
@property(nonatomic,assign) UIEdgeInsets contentInsts;

@property(nonatomic,assign) MKUIListViewScrollDirection scrollDirection;
@property(nonatomic,readonly) MKCGAxis scrollAxis;
@end
NS_ASSUME_NONNULL_END
